package com.ruoyi;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huobi.client.SubscriptionClient;
import com.huobi.client.SubscriptionOptions;
import com.ruoyi.common.constant.CacheKeyConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.TradeType;
import com.ruoyi.common.utils.AESUtil;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.WdyHuobiTrade;
import com.ruoyi.system.domain.WdyWithdraw;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.IWdyHuobiTradeService;
import com.ruoyi.system.service.IWdyWithdrawService;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.List;
import java.util.TimeZone;

/**
 * 启动程序
 * 
 * @author ruoyi
 */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@MapperScan("com.ruoyi.*.mapper")
public class RuoYiApplication implements CommandLineRunner
{
    private static final Logger logger = LoggerFactory.getLogger(RuoYiApplication.class);
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private IWdyHuobiTradeService wdyHuobiTradeService;
    @Autowired
    private IWdyWithdrawService wdyWithdrawService;
    public static void main(String[] args)
    {
        // System.setProperty("spring.devtools.restart.enabled", "false");
        System.out.println(String.format("===============当前时间：%s================", DateUtils.getTime()));
        SpringApplication.run(RuoYiApplication.class, args);
        System.out.println("(♥◠‿◠)ﾉﾞ  钱包启动成功   ლ(´ڡ`ლ)ﾞ  \n" +
                " .-------.       ____     __        \n" +
                " |  _ _   \\      \\   \\   /  /    \n" +
                " | ( ' )  |       \\  _. /  '       \n" +
                " |(_ o _) /        _( )_ .'         \n" +
                " | (_,_).' __  ___(_ o _)'          \n" +
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
                " |  | \\ `'   /|   `-'  /           \n" +
                " |  |  \\    /  \\      /           \n" +
                " ''-'   `'-'    `-..-'              ");
        System.out.println(String.format("===============当前时间：%s================", DateUtils.getNowDate()));
    }

    @PostConstruct
    void setDefaultTimezone() {
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
//        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Aden"));
    }

    @Override
    public void run(String... args) throws Exception {
//        initWithdrawRemark();


        BigDecimal usdtCny = new BigDecimal(sysConfigService.selectConfigByKey(Constants.USDT_CNY));
        redisTemplate.opsForHash().putIfAbsent(CacheKeyConstants.EXCHANGE_RATE, Constants.USDT_CNY, usdtCny);

        // Subscribe 24HTradeStatistics with custom server
        SubscriptionOptions options = new SubscriptionOptions();
        SubscriptionClient subscriptionClient = SubscriptionClient.create("", "", options);
        subscriptionClient.subscribe24HTradeStatisticsEvent("btcusdt,ethusdt,eosusdt", (statisticsEvent) -> {
//            System.out.println("-------------Subscribe 24H Trade Statistics-------------");
//            System.out.println("Timestamp: " + statisticsEvent.getData().getTimestamp());
//            System.out.println("High: " + statisticsEvent.getData().getHigh());
//            System.out.println("Low: " + statisticsEvent.getData().getLow());
//            System.out.println("Open: " + statisticsEvent.getData().getOpen());
//            System.out.println("Close: " + statisticsEvent.getData().getClose());
//            System.out.println("Volume: " + statisticsEvent.getData().getVolume());

            redisTemplate.opsForHash().put(CacheKeyConstants.HUOBI_TRADESTATISTICS_24H, statisticsEvent.getSymbol(), statisticsEvent.getData());

            if(!"ethusdt".equals(statisticsEvent.getSymbol())) {
                return;
            }

            BigDecimal dealPrice = statisticsEvent.getData().getClose();
            BigDecimal curUsdtCny = (BigDecimal) redisTemplate.opsForHash().get(CacheKeyConstants.EXCHANGE_RATE, Constants.USDT_CNY);
            dealPrice = BigDecimalUtil.getPDecimal(BigDecimalUtil.multiply(dealPrice, curUsdtCny), 4);

            QueryWrapper<WdyHuobiTrade> buyTradeQuery = new QueryWrapper<>();
            buyTradeQuery.select("id", "user_id", "trade_type", "trade_amount", "trade_price");
            buyTradeQuery.eq("trade_type", TradeType.BUY.getCode());
            buyTradeQuery.eq("trade_state", WdyHuobiTrade.STATE_TRADE);
            buyTradeQuery.ge("trade_price", dealPrice);
            List<WdyHuobiTrade> buyTradeList = wdyHuobiTradeService.list(buyTradeQuery);
            deal(buyTradeList);
            QueryWrapper<WdyHuobiTrade> sellTradeQuery = new QueryWrapper<>();
            sellTradeQuery.select("id", "user_id", "trade_type", "trade_amount", "trade_price");
            sellTradeQuery.eq("trade_type", TradeType.SELL.getCode());
            sellTradeQuery.eq("trade_state", WdyHuobiTrade.STATE_TRADE);
            sellTradeQuery.le("trade_price", dealPrice);
            List<WdyHuobiTrade> sellTradeList = wdyHuobiTradeService.list(sellTradeQuery);
            deal(sellTradeList);
        });

//        subscriptionClient.subscribeTradeEvent("btcusdt,ethusdt,eosusdt", tradeEvent -> {
//            System.out.println("------------Subscribe Trade Event-------------");
//            tradeEvent.getTradeList().forEach(trade -> {
//                System.out.println(JSON.toJSONString(trade));
//                System.out.println("id:" + trade.getTradeId() + " price:" + trade.getPrice() + " amount:" + trade.getAmount() + " direction:" + trade.getDirection());
//            });
//            redisTemplate.opsForHash().put(CacheKeyConstants.HUOBI_TRADE_DETAIL, tradeEvent.getSymbol(), tradeEvent.getTradeList());
//        });
    }

    private void initWithdrawRemark() {
        logger.info("===============开始initWithdrawRemark================");
        QueryWrapper<WdyWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "remark");
        List<WdyWithdraw> list = wdyWithdrawService.list(queryWrapper);
        if(!CollectionUtils.isEmpty(list)) {
            for(WdyWithdraw w : list) {
                if(StringUtils.isNotEmpty(w.getRemark())) {
                    String remark = AESUtil.decrypt(w.getRemark());
                    if(StringUtils.isEmpty(remark)) {
                        UpdateWrapper<WdyWithdraw> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("id", w.getId());
                        updateWrapper.set("remark", AESUtil.encrypt(w.getRemark()));
                        wdyWithdrawService.update(updateWrapper);
                        logger.info("=========initWithdrawRemark:{}============" + w.getId());
                    }
                }
            }
        }
        logger.info("===============结束initWithdrawRemark================");
    }

    private void deal(List<WdyHuobiTrade> tradeList) {
        if(!CollectionUtils.isEmpty(tradeList)) {
            tradeList.forEach(t -> {
                try {
                    wdyHuobiTradeService.deal(t);
                } catch (Exception e) {
                    logger.error("成交异常", e);
                }

            });
        }
    }
}